package fun.sssdnsy.util;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.nio.file.Files;
import java.security.Security;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;

/**
 * 加密工具类
 * - 负责对用户数据进行加密存储
 * - 默认使用 SM4 128-bit 加密，可扩展支持 AES、SM2、SM3
 * - 密钥从 config.json 读取
 *
 * @author pengzh
 * @since 2025-03-30
 */
public class CryptoUtil {
    private static final transient Logger log = LoggerFactory.getLogger(CryptoUtil.class);

    private static final String CONFIG_PATH = "config.json";
    public static final String ALGORITHM_SM4 = "SM4";
    public static final String ALGORITHM_AES = "AES";
    // 默认使用 SM4
    public static final String DEFAULT_ALGORITHM = ALGORITHM_SM4;
    public static final String DEFAULT_KEY = "123456";
    private static Cipher cipher;

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static void init() {
        CompletableFuture.runAsync(() -> {
            String defaultAlgorithm = ConfigUtil.get("encryptionAlgorithm", DEFAULT_ALGORITHM);
            String defaultEncyptKey = ConfigUtil.get("encryptionKey", DEFAULT_KEY);
            try {
                cipher = getCipher(defaultAlgorithm, Cipher.DECRYPT_MODE, defaultEncyptKey);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(e);
            }
        }, ThreadPoolUtil.ASYNC_POOL);
    }

    public static byte[] generate128bitKey(String password) {
        byte[] passwordBytes = password.getBytes();
        SM3Digest sm3 = new SM3Digest();
        sm3.update(passwordBytes, 0, passwordBytes.length);
        byte[] hash = new byte[32];  // SM3 生成 32 字节（256-bit）
        sm3.doFinal(hash, 0);
        return Arrays.copyOf(hash, 16);  // 取前 16 字节作为 SM4 密钥
    }


    /**
     * 加密文本并保存到文件
     */
    public static void encryptToFile(String data, File file) {
        try {
            byte[] encrypted = encrypt(data.getBytes(), DEFAULT_ALGORITHM, ConfigUtil.get("encryptionKey", "123456786"));
            Files.write(file.toPath(), encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 读取文件并解密
     */
    public static String decryptFile(File file) {
        try {
            byte[] encrypted = Files.readAllBytes(file.toPath());
            return new String(decrypt(encrypted, DEFAULT_ALGORITHM, ConfigUtil.get("encryptionKey", "123456786")));
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 通用加密方法，支持 AES 和 SM4
     */
    public static byte[] encrypt(byte[] data, String algorithm, String password) throws Exception {
        Cipher cipher = getCipher(algorithm, Cipher.ENCRYPT_MODE, password);
        return cipher.doFinal(data);
    }

    /**
     * 通用解密方法，支持 AES 和 SM4
     */
    public static byte[] decrypt(byte[] data, String algorithm, String password) throws Exception {
        return cipher.doFinal(data);
    }

    /**
     * 获取 Cipher 实例，支持 AES 和 SM4
     */
    private static Cipher getCipher(String algorithm, int mode, String password) throws Exception {
        String transformation = algorithm.equals("SM4") ? "SM4/ECB/PKCS5Padding" : "AES/ECB/PKCS5Padding";
        Cipher cipher = Cipher.getInstance(transformation);
        byte[] keyBytes = generate128bitKey(password); // 统一在这里转换密钥
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, algorithm);
        cipher.init(mode, secretKey);
        return cipher;
    }

}
